package data_process

import (
	"fmt"
	"reflect"
	"scoce_estimate/model"
	"scoce_estimate/status"
	"scoce_estimate/utils/database"
	"sync"
)

type Search_key struct {
	User_id    string
	Problem_id int
}

type Search_result struct {
	Score  int
	Status int
}

var csp_j_rank []int = make([]int, 401)
var csp_s_rank []int = make([]int, 401)
var total_map = map[string]bool{}
var csp_j_total int = 0
var csp_s_total int = 0
var mutex sync.RWMutex

func Insert(user_id string, problem_id int, score int, status int) {
	mutex.Lock()
	defer mutex.Unlock()
	s := Search_key{User_id: user_id, Problem_id: problem_id}
	data.Insert(s, Search_result{Score: score, Status: status})
}

func AddRanking(user_id string, total int, level int) {
	_, ok := total_map[user_id]
	if ok {
		return
	}
	total_map[user_id] = true

	if level == status.CSPJ_LEVEL {
		csp_j_rank[total]++
		csp_j_total++
	} else if level == status.CSPS_LEVEL {
		csp_s_rank[total]++
		csp_s_total++
	}
}
func GetRanking(total int, level int) int {
	rank := 1
	var stats []int
	if level == status.CSPJ_LEVEL {
		stats = csp_j_rank
	} else if level == status.CSPS_LEVEL {
		stats = csp_s_rank
	}

	for i := total + 1; i < 401; i++ {
		rank += stats[i]
	}
	return rank
}

func GetCSPJTotal() int {
	return csp_j_total
}

func GetCSPSTotal() int {
	return csp_s_total
}

// return score if exist, return -1 if not exist
func GetScore(user_id string, problem_id int) Search_result {

	s := Search_key{User_id: user_id, Problem_id: problem_id}
	mutex.Lock()
	defer mutex.Unlock()

	tmp, ok := data.Inspect(s)

	if !ok {
		return Search_result{Score: -1, Status: status.NOT_EXIST}
	}
	if reflect.TypeOf(tmp).Kind() != reflect.TypeOf(Search_result{}).Kind() {
		fmt.Println("内存中数据类型不一致")
		panic("内存中数据类型不一致")
	}
	res := (tmp).(Search_result)

	if ok && res.Status == status.HAS_RESULT {
		return res
	}

	solution := &model.Solution{}
	solution.Problem_id = problem_id
	solution.User_id = user_id
	database.GetDB().Where("problem_id=? and user_id=?", solution.Problem_id, solution.User_id).Find(solution)
	if solution.Solution_id == 0 {
		sr := Search_result{Score: -1, Status: status.NOT_IN_QUEUE}
		data.Insert(s, sr)
		return sr
	}
	if solution.Result <= 3 || solution.Result >= 14 {
		sr := Search_result{Score: -1, Status: status.IN_QUEUE}
		data.Insert(s, sr)
		return sr
	}
	sr := Search_result{Score: int(solution.Pass_rate * 100), Status: status.HAS_RESULT}
	data.Insert(s, sr)
	return sr

}
